#include "timer_pwm.h"

TIM_HandleTypeDef htim1;

// USER CONFIG
#define SYSTEM_CLOCK        (24000000) // 系统频率Hz
#define PWM_FREQ            (25000) // PWM频率Hz
#define PWM_DUTY_DEFAULT    (50)  // PWM默认占空比
// 定时器参数配置，不可修改
#define SYSTEM_CLOCK_PRESCALER      (0)       // 系统时钟预分频
#define PWM_PERIOD                  (SYSTEM_CLOCK / PWM_FREQ - 1) // 定时器周期值
#define PWM_DUTY_MIN                (0)
#define PWM_DUTY_MAX                (100)
#define PWM_PULSE_DEFAULT           (PWM_DUTY_DEFAULT * (PWM_PERIOD + 1) / 100)

/**
 * @brief 配置高级定时器TIM1输出25KHz的PWM
 * @note  系统频率24MHz
 */
void timer1_pwm_init(void)
{
    // 使能时钟
    __HAL_RCC_TIM1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    // 配置定时器基础参数
    htim1.Instance = TIM1;
    htim1.Init.Prescaler = SYSTEM_CLOCK_PRESCALER; // 不分频，计数频率=24MHz
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim1.Init.Period = PWM_PERIOD; // 25kHz PWM: 24MHz / 960 = 25kHz
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim1.Init.RepetitionCounter = 0;
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    HAL_TIM_PWM_Init(&htim1);

    // 配置PWM通道
    TIM_OC_InitTypeDef sConfigOC = {0};
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = PWM_PULSE_DEFAULT; // 默认50%占空比: 480/960 = 50%
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);

    // 启动PWM输出
    // HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); // 启动互补通道PWM输出

    // 配置PA7为TIM1_CH1N
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF2_TIM1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

static inline uint8_t pwm_duty_limit(const uint8_t duty)
{
    if (duty < PWM_DUTY_MIN)
        return PWM_DUTY_MIN;
    if (duty > PWM_DUTY_MAX)
        return PWM_DUTY_MAX;
    return duty;
}

/**
 * @brief 修改PWM占空比
 * @param duty 占空比 (0 ~ 100)
 */
void timer1_set_pwm_duty(const uint8_t duty)
{
    uint8_t current_duty = duty;
    uint32_t pulse = (uint32_t)((htim1.Init.Period + 1) * current_duty / 100);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pulse);
}

/**
 * @brief 获取当前PWM占空比
 * @return 占空比 (0 ~ 100)
 */
uint8_t timer1_get_pwm_duty(void)
{
    uint32_t current_pulse = __HAL_TIM_GET_COMPARE(&htim1, TIM_CHANNEL_1);
    uint32_t period = htim1.Init.Period + 1;
    return (uint8_t)((current_pulse * 100) / period);
}
